package com.aioething.iot.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONObject;
import com.aioething.iot.beans.RegisterRequest;
import com.aioething.iot.beans.RegisterResponse;
import com.aioething.iot.dao.EquipmentDao;
import com.aioething.iot.dao.ProductDao;
import com.aioething.iot.dto.EquipmentDto;
import com.aioething.iot.model.Equipment;
import com.aioething.iot.model.Product;
import com.aioething.iot.service.IEmqxService;
import com.aioething.iot.service.IEquipmentService;
import com.aioething.iot.vo.EquipmentVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class EquipmentService implements IEquipmentService {
    @Autowired
    private EquipmentDao equipmentDao;
    @Autowired
    private ProductDao productDao;
    @Autowired
    private IEmqxService emqxService;

    @Override
    public int save(Equipment equipment) {
        Equipment exists = equipmentDao.selectByPrimaryKey(equipment.getEquipmentId());
        if (ObjectUtil.isNull(exists)) {
            return equipmentDao.insertSelective(equipment);
        } else {
            return equipmentDao.updateByPrimaryKeySelective(equipment);
        }
    }

    @Override
    public int delete(String equipmentId) {
        return equipmentDao.deleteByPrimaryKey(equipmentId);
    }

    @Override
    public int update(Equipment equipment) {
        Equipment exists = equipmentDao.selectByPrimaryKey(equipment.getEquipmentId());
        if (ObjectUtil.isNull(exists))  return 0;
        JSONObject reported = exists.getReported();
        if (ObjectUtil.isNotNull(equipment.getReported())) {
            for (String key : equipment.getReported().keySet()) {
                reported.set(key, equipment.getReported().get(key));
            }
        }
        equipment.setReported(reported);
        JSONObject desired = exists.getDesired();
        if (ObjectUtil.isNotNull(equipment.getDesired())) {
            for (String key : equipment.getDesired().keySet()) {
                desired.set(key, equipment.getDesired().get(key));
            }
        }
        equipment.setDesired(desired);
        // 计算差异
        JSONObject delta = exists.getDelta();
        for (String key : desired.keySet()) {
            if (ObjectUtil.notEqual(desired.get(key), reported.get(key))) {
                delta.set(key, desired.get(key));
            } else {
                delta.remove(key);
            }
        }
        equipment.setDelta(delta);
        if (!delta.isEmpty()) {
            // 发送mqtt消息
            String topic = String.format("things/%s/%s/property/down", equipment.getProductId(), equipment.getDeviceName());
            try {
                HttpResponse response = emqxService.publish(topic, delta.toString());
                if (response.getStatus() != HttpStatus.HTTP_OK) {
                    log.error(response.body());
                }
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        }
        return equipmentDao.updateByPrimaryKeySelective(equipment);
    }

    @Override
    public PageInfo<EquipmentVo> query(EquipmentDto equipmentDto) {
        PageHelper.startPage(equipmentDto.getPageNo(), equipmentDto.getPageSize());
        List<EquipmentVo> list = equipmentDao.query(equipmentDto);
        return new PageInfo<>(list);
    }

    @Override
    public RegisterResponse register(RegisterRequest request) {
        RegisterResponse response = new RegisterResponse();
        Product product = productDao.selectByProductId(request.getProductId());
        if (ObjectUtil.isNull(product)) {
            response.setCode(RegisterResponse.INVALID_PRODUCT);
            return response;
        }
        if (ObjectUtil.notEqual(request.getProductKey(), product.getProductKey())) {
            response.setCode(RegisterResponse.PRODUCT_KEY_ERROR);
            return response;
        }
        Equipment equipment = equipmentDao.selectByPrimaryKey(request.getDeviceId());
        if (ObjectUtil.isNull(equipment)) {
            equipment = new Equipment();
            equipment.setEquipmentId(request.getDeviceId());
            equipment.setPsk(IdUtil.fastSimpleUUID());
            equipment.setCreateTime(new Date());
            equipmentDao.insertSelective(equipment);
        }
        response.setCode(RegisterResponse.SUCCESS);
        response.setPsk(equipment.getPsk());
        return response;
    }
}
